package com.bjf.db.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.bjf.db.dao.bean.Page;
import com.bjf.db.dao.bean.Result;
import com.bjf.db.dao.iface.ICommQueryDAO;
import com.bjf.util.PageUtil;

public class CommQueryDAO extends HibernateDaoSupport implements ICommQueryDAO{
	
	public CommQueryDAO() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * Execute a query.
     * @param query a query expressed in Hibernate's query language
     * @return a distinct list of instances (or arrays of instances)
     */
    public List find(String query) {
        return getHibernateTemplate().find(query);
    }

    /**
     * Obtain an instance of Query for a named query string defined in the mapping file.
     * @param name the name of a query defined externally
     * @return Query
     */
    public List findByNamedQuery(String name) {
        return getHibernateTemplate().findByNamedQuery(name);
    }

    public List findByNamedQuery(final String name, final int begin, final int count) {
        return getHibernateTemplate().executeFind(
            new HibernateCallback() {
                public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                    Query query = session.getNamedQuery(name);
                    if( begin >= 0 ) {
                        query.setFirstResult(begin);
                        query.setMaxResults(count);
                    }
                    return query.list();
                }
            }
        );
    }

    /**
     * Obtain an instance of Query for a named query string defined in the mapping file.
     * Use the parameters give
     * @param name the name of a query defined externally
     * @param params the parameter Map
     * @return Query
     */
    public List findByNamedQuery(final String name, final Map params) {
        return findByNamedQuery(name, params, -1, -1);
    }

    public List findByNamedQuery(final String name, final Map params, final int begin, final int count) {
        return getHibernateTemplate().executeFind(
            new HibernateCallback() {
                public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                    Query query = session.getNamedQuery(name);
                    if (null != params) {
                        for (Iterator i=params.entrySet().iterator(); i.hasNext(); ) {
                            Map.Entry entry = (Map.Entry) i.next();
                            query.setParameter((String) entry.getKey(), entry.getValue());
                        }
                    }
                    if( begin >= 0 ) {
                        query.setFirstResult(begin);
                        query.setMaxResults(count);
                    }
                    return query.list();
                }
            }
        );
    }

    /**
     * Obtain an instance of Query for a named query string defined in the mapping file.
     * Use the parameters give
     * @param name the name of a query defined externally
     * @param params the parameter array
     * @return Query
     */
    public List findByNamedQuery(final String name, final Serializable[] params) {
        return findByNamedQuery(name, params, -1, -1);
    }

    /**
     * Obtain an instance of Query for a named query string defined in the mapping file.
     * Use the parameters give
     * @param name the name of a query defined externally
     * @param params the parameter array
     * @return Query
     */
    public List findByNamedQuery(final String name, final Serializable[] params, final int begin, final int count) {
        return getHibernateTemplate().executeFind(
            new HibernateCallback() {
                public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                    Query query = session.getNamedQuery(name);
                    if (null != params) {
                        for (int i = 0; i < params.length; i++) {
                            query.setParameter(i, params[i]);
                        }
                    }
                    if( begin >= 0 ) {
                        query.setFirstResult(begin);
                        query.setMaxResults(count);
                    }
                    return query.list();
                }
            }
        );
    }

    /* (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findBySQLQuery(java.lang.String, int, int)
     */
    public java.util.List findBySQLQuery(final String sql,final int begin, final int count){
         return getHibernateTemplate().executeFind(
                    new HibernateCallback() {
                        public Object doInHibernate(Session session)
                            throws HibernateException, SQLException {
                            Query query = session.createSQLQuery(sql);
                            if( begin >= 0 ) {
                                query.setFirstResult(begin);
                                query.setMaxResults(count);
                            }
                            return query.list();
                        }
                    }
                );
    }

    @SuppressWarnings("unchecked")
    public List findByPreparedStatment(final String name, final Map params) {


        return getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createQuery(name);
                        if (null != params) {
                            for (Iterator i=params.entrySet().iterator(); i.hasNext(); ) {
                                Map.Entry entry = (Map.Entry) i.next();
                                query.setParameter((String) entry.getKey(), entry.getValue());
                            }
                        }
                        return query.list();
                    }
                }
            );
    }
    @SuppressWarnings("unchecked")
    public List findByPreparedSQL(final String sql, final Map params){
        System.out.println(sql);
        Iterator it = params.entrySet().iterator();
        while(it.hasNext()){
            Entry e = (Entry)it.next();
            System.out.println(e.getKey() + ":" + e.getValue());
        }

        return getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createSQLQuery(sql);
                        if (null != params) {
                            for (Iterator i=params.entrySet().iterator(); i.hasNext(); ) {
                                Map.Entry entry = (Map.Entry) i.next();
                                query.setParameter((String) entry.getKey(), entry.getValue());
                            }
                        }
                        return query.list();
                    }
                }
            );
    }

    /* (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findBySQLQuery(java.lang.String, java.lang.String, int, int)
     */
    public Result findBySQLQuery(final String sql,final String countSql,final int begin, final int count){
        int currentPage = begin/count;
        if(begin%count != 0){
            currentPage++;
        }
        String allCount = findCountBySQLQuery(countSql);
        List data = getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createSQLQuery(sql);
                        if( begin >= 0 ) {
                            query.setFirstResult(begin);
                            query.setMaxResults(count);
                        }
                        return query.list();
                    }
                }
        );

        Page page = PageUtil.createPage(count,currentPage + 1,Integer.parseInt(allCount));
        return new Result(page,data);
    }

    /* (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findCountBySQLQuery(java.lang.String)
     */
    public String findCountBySQLQuery(final String countSql){
        List data = getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createSQLQuery(countSql);
                        return query.list();
                    }
                }
        );
        if (data.size() == 0)
			return "0";
		if (data.size() > 1)
			return String.valueOf(data.size());
		if (countSql.contains("group by"))
			return String.valueOf(data.size());
		return data.get(0).toString();
    }

    /*
     * (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findBySQLQuery(java.lang.String)
     */
    public List findBySQLQuery(final String sql){
        List data = getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createSQLQuery(sql);
                        return query.list();
                    }
                }
        );
        return data;
    }

     public void updBySQL(String sqlStr) {

            try {
                 getHibernateTemplate().getSessionFactory().getCurrentSession().createSQLQuery(sqlStr).executeUpdate();
            }catch (HibernateException ex) {
                ex.printStackTrace();
                logger.error("execute sql error:" + sqlStr, ex);
                throw ex;
            }
     }
    /*
     * (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findByHQLQuery(java.lang.String)
     */
    public List findByHQLQuery(final String hql){
        List data = getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createQuery(hql);
                        return query.list();
                    }
                }
        );
        return data;
    }

    /*
     * (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findByHQLQuery(java.lang.String, int, int)
     */
    public java.util.List findByHQLQuery(final String hql,final int begin, final int count){
     return getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createQuery(hql);
                        if( begin >= 0 ) {
                            query.setFirstResult(begin);
                            query.setMaxResults(count);
                        }
                        return query.list();
                    }
                }
            );
    }

    /*
     * (non-Javadoc)
     * @see com.huateng.commquery.dao.ICommQueryObj#findByHQLQuery(java.lang.String, java.lang.String, int, int)
     */
    public Result findByHQLQuery(final String hql,final String countSql,final int begin, final int count){
        int currentPage = begin/count;
        if(begin%count != 0){
            currentPage++;
        }
        String allCount = findCountBySQLQuery(countSql);
        List data = getHibernateTemplate().executeFind(
                new HibernateCallback() {
                    public Object doInHibernate(Session session)
                        throws HibernateException, SQLException {
                        Query query = session.createQuery(hql);
                        if( begin >= 0 ) {
                            query.setFirstResult(begin);
                            query.setMaxResults(count);
                        }
                        return query.list();
                    }
                }
        );

        Page page = PageUtil.createPage(count,currentPage + 1,Integer.parseInt(allCount));
        return new Result(page,data);
    }


    public void flush() {
        getHibernateTemplate().flush();
    }



    @SuppressWarnings("unchecked")
    public int getRecCountByHQL( String query){
    List list=  this.findByHQLQuery(query);
    Object o = list.get(0);
    int totalCount = Integer.parseInt(String.valueOf(o).trim());

        return totalCount;
    }
    
    /**
     * findByWhere
     * @param poClass
     * @param where
     * @return
     */
    public List findByWhere(Class poClass, String where) {
		try {
			return getHibernateTemplate().find(
				new StringBuilder("from ").append(poClass.getName()).append(" po where ")
					.append(where).toString());
		} catch (RuntimeException re) {
			logger.error(new StringBuilder("findByWhere ").append(poClass.getSimpleName())
				.append(" error").toString(), re);
			throw re;
		}
	}
    
    /**
     * findByWhere
     * @param poClass
     * @param where
     * @param values
     * @return
     */
    public List findByWhere(Class poClass, String where, Object[] values) {
		try {
			return getHibernateTemplate().find(
				new StringBuilder("from ").append(poClass.getName()).append(" po where ")
					.append(where).toString(), values);
		} catch (RuntimeException re) {
			logger.error(new StringBuilder("findByWhere ").append(poClass.getSimpleName())
					.append(" error").toString(), re);
				throw re;
			}
	}
    
    public List findByHQLQueryWithParams(final String hql, final int begin, final int count,
    		final Serializable[] params) {
    	 List data = getHibernateTemplate().executeFind(
                 new HibernateCallback() {
                     public Object doInHibernate(Session session)
                         throws HibernateException, SQLException {
                         Query query = session.createQuery(hql);
                         if (null != params) {
                             for (int i = 0; i < params.length; i++) {
                                 query.setParameter(i, params[i]);
                             }
                         }
                         if( begin >= 0 ) {
                             query.setFirstResult(begin);
                             query.setMaxResults(count);
                         }
                         return query.list();
                     }
                 }
         );
         return data;
    }
    
    public HibernateTemplate getHibernateTemplateNew() {
    	// TODO Auto-generated method stub
    	return super.getHibernateTemplate();
    }
    
}
